package com.easy.secret.interceptor;

import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
import java.util.Properties;

import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.easy.secret.annotation.SecureData;
import com.easy.secret.service.SecureService;

import lombok.extern.slf4j.Slf4j;

/**
 * @ProjectName: esay-secret-server
 * @Package: com.easy.secret.interceptor
 * @ClassName: DecryptInterceptor
 * @Description: jmybatis的解密拦截器
 * @Author: wangjc
 * @CreateDate: 2023/11/17
 * @UpdateUser: wangjc
 * @UpdateDate: 2023/11/17
 * @UpdateRemark: 更新内容
 * @Version: 1.0
 */

@Slf4j
@Component
@Intercepts({
        @Signature(
        type = ResultSetHandler.class,
        method = "handleResultSets",
        args = {Statement.class}
)})
public class DecryptInterceptor implements Interceptor {

    @Autowired
    private SecureService secureService;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.debug("------into decrypt interceptor------");
        Object resultObject = invocation.proceed();
        if (Objects.isNull(resultObject)) {
            return null;
        }

        if (resultObject instanceof ArrayList) {
            // 结果集为list集合
            ArrayList resultList = (ArrayList) resultObject;
            if (!CollectionUtils.isEmpty(resultList) && this.needToDecrypt(resultList.get(0))) {
                Iterator iterator = resultList.iterator();

                while (iterator.hasNext()) {
                    Object result = iterator.next();
                    try {
                        secureService.decrypt(result);
                    } catch (Exception e) {
                        log.error("解密实体对象异常: {}", e);
                    }
                }
            }
        } else if (this.needToDecrypt(resultObject)) {
            // 结果集为实体类，并且需要解密
            try {
                secureService.decrypt(resultObject);
            } catch (Exception e) {
                log.error("解密实体对象异常: {}", e);
            }
        }
        return resultObject;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

    /**
     * 是否需要加解密
     *
     * @param object
     * @return
     */
    private boolean needToDecrypt(Object object) {
        if(Objects.isNull(object)) {
            return false;
        }
        Class<?> objectClass = object.getClass();
        SecureData sensitiveData = AnnotationUtils.findAnnotation(objectClass, SecureData.class);
        return Objects.nonNull(sensitiveData);
    }
}
